package com.solution.wx.my.controller;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.solution.admin.auth.entity.UserEntity;
import com.solution.admin.auth.security.UsernamePasswordToken;
import com.solution.admin.auth.service.UserService;
import com.solution.admin.customer.entity.CustomerEntity;
import com.solution.admin.customer.service.CustomerService;
import com.solution.admin.home.service.RedisService;
import com.solution.admin.settings.entity.KeyMapEntity;
import com.solution.admin.settings.service.KeyMapService;
import com.solution.common.config.PublicConfigUtil;
import com.solution.common.constants.PublicStatus;
import com.solution.common.constants.PublicStatus.USER_APPROVE_STATUS;
import com.solution.common.constants.PublicStatus.USER_TYPE;
import com.solution.common.controller.BaseController;
import com.solution.common.utils.RandomUtils;
import com.solution.common.utils.ip.IPUtils;
import com.solution.common.utils.sms.AliyunSmsUtils;
import com.solution.common.utils.string.StringUtil;
import com.solution.pc.home.constants.HomeConstants.SmsTemplateType;
import com.solution.wx.core.constants.WechatConstants;
import com.solution.wx.core.util.WechatUtil;
import com.solution.wx.my.constants.MyConstants;

/**
 * 微信绑定账号控制层
 * @author: solin
 * @date: 2017年11月16日 下午4:57:01
 */
@RequestMapping("/wx/my")
@Controller("wxBindAccountController")
public class BindAccountController extends BaseController{
	
	private Logger logger = LoggerFactory.getLogger(BindAccountController.class);
	
	@Autowired
    private RedisService redisService;
	
	@Autowired
	private CustomerService customerService;
	
	@Autowired
	private UserService userService;
	
	@Autowired
	private KeyMapService keyMapService;
	
	/**
	 * 跳转到绑定页面
	 * 微信公众号的菜单现在会出现两种情况： 1.不登录也可以直接进入页面的，如首页  2.需要登录才能进入的，如报价单
	 * 
	 *  
	 *  
	 * @param request
	 * @param model
	 * @return
	 * @author: solin
	 * @date: 2017年11月16日 下午4:58:33
	 */
	@RequestMapping("/toBindAccountPage")
	public String toBindAccountPage(HttpServletRequest request){
		//指定跳转的url
		String goToUrl = request.getParameter("goToUrl");
		String openId = WechatUtil.getOpenIdFromCookie(request);
		// 如果cookie 中没有openId，或者有openid,未登录
		if (StringUtil.isEmpty(openId)) {
			// 新用户，判断地址是否可以直接访问，如果可以则直接放行；否则进入授权页面
			//如果有定向跳转的url则将该地址继续传递
			if (StringUtil.isNotNull(goToUrl)) {
				goToUrl = decodeGoToURL(goToUrl);
				// 判断是否可以放行
				/**
				boolean directAccessFlag = isDirectAccessWechatMenu(goToUrl);
				if(directAccessFlag){
					return "redirect:"+goToUrl;
				}else{
					String requestParam = request.getQueryString();
					String authorizeUrl = redirectToAuth(requestParam);
					return authorizeUrl;
				}*/
				
				String requestParam = request.getQueryString();
				String authorizeUrl = redirectToAuth(requestParam);
				return authorizeUrl;
				
			}else{
				String requestParam = "goToUrl=%2Fwx%2Findex";
				String authorizeUrl = redirectToAuth(requestParam);
				// 首页授权跳转
				return authorizeUrl;
			}
		}
		// 有openid 未登录或登录会话过期
		if(!isLogin(request)){
			// 可以直接跳转
			if (StringUtil.isNotNull(goToUrl)) {
				goToUrl = decodeGoToURL(goToUrl);
				// 判断是否可以放行
				/**
				boolean directAccessFlag = isDirectAccessWechatMenu(goToUrl);
				if(directAccessFlag){
					return "redirect:"+goToUrl;
				}
				*/
			}
			
			// 页面是否显示注册链接标记
			boolean showRegisterLink = true;
			//判断openId是否已经关联客户信息,如果有该openId的用户，再次调用登录
			Map<String, Object> param = new HashMap<String, Object>();
			param.put("openId", openId);
			List<UserEntity> userList = userService.getUserList(param);
			for (UserEntity user : userList) {
				//shiro登录
				Subject currentUser = SecurityUtils.getSubject();
				UsernamePasswordToken token = new UsernamePasswordToken();
				// 设置用户史
				token.setUsername(user.getUserCode());
				// 设置密码
				token.setPassword(user.getPassword().toCharArray());
				// 设备终端登录
				token.setLoginTerminal(PublicStatus.LOGIN_TERMINAL_TYPE.WX.getCode());
				// 调用登录
				currentUser.login(token);
				// 登录成功后，不再显示注册连接
				showRegisterLink = false;
				//跳转到首页 userType = 4 ,代表是客户
				if (USER_TYPE.CUSTOMER.getId().equals(user.getUserType())) {
					//如果有指定调整地址,则转入该地址
					if (StringUtil.isNotNull(goToUrl)) {
						goToUrl = decodeGoToURL(goToUrl);
						return "redirect:"+goToUrl;
					}else{
						return "redirect:/wx/index";
					}
				}else{
					// 商务员，跳转商务首页
					return "redirect:/wx/index";
				}
			}
			// 如果用户不都存在，则跳转到绑定页面
			request.setAttribute("showRegisterLink", showRegisterLink);
			return "wx/my/bindAccount";
		}
		
		
		if(StringUtil.isEmpty(goToUrl)){
			if(StringUtil.isNotEmpty(openId)){
				return "/wx/my/bindAccount";
			}else{
				// 进入绑定页面前，首先要获取到openid,写入cookie
				goToUrl =  encodeGoToURL("/wx/my/toBindAccountPage");
				String requestParam =  WechatConstants.SRC_PAGE_URL_KEY.concat("="+goToUrl);
				String authUrl = redirectToAuth(requestParam);
				return authUrl;
			}
		}
		
		// 如果已经登录,直接跳转连接
		if(isLogin(request)){
			if (StringUtil.isNotNull(goToUrl)) {
				goToUrl = decodeGoToURL(goToUrl);
				return "redirect:"+goToUrl;
			}
		}
		return "/wx/index";
	}
	
	
	/**
	 * 组织跳转授权的连接
	 * @param requestParam  查询参数，格式如： srcPageUrl = http://www.baidu.com
	 * @return
	 */
	private String redirectToAuth(String requestParam){
		String state = "123";
		// 回调地址  /wx/authSuccess
		String redirect_uri = PublicConfigUtil.readConfig("auth_redirect");
		if (StringUtil.isNotEmpty(requestParam)) {
			redirect_uri = (redirect_uri + "?").concat(requestParam);
		}
		// 需要对回调地址进行编码
		String encode_redirect_uri = encodeGoToURL(redirect_uri);
		// 拼接微信认证地址
		String authorizeUrl = WechatUtil.AUTHORIZE_URL
				.replace("APPID", WechatUtil.APPID)
				.replace("ENCODE_REDIRECT_URI", encode_redirect_uri)
				.replace("SCOPE", WechatUtil.SCOPE_SNSPAIUSERINFO)
				.replace("STATE", state);
		return "redirect:" + authorizeUrl;
	}
	
	/**
	 * 查询正在访问的微信公众号菜单是否可以直接进入（匿名访问）
	 * @param requestParam
	 * @return
	 */
	private boolean isDirectAccessWechatMenu(String goToUrl){
		// 微信公众号菜单跳转地址
		boolean allowAccessFlag = true;
		if(StringUtil.isNotEmpty(goToUrl)){
			// 判断地址是否需要授权
			// 查询微信菜单需要授权的菜单地址
			List<KeyMapEntity> kmList = keyMapService.listKeyMap("wechatMenuAuth");
			
			if(kmList != null && kmList.size() > 0){
				for (KeyMapEntity kv : kmList) {
					if(kv.getKeyValue().equals(goToUrl)){
						allowAccessFlag = false;
					}
				}
			}
		}
		return allowAccessFlag;
	}
	
	
	/**
	 * 对微信公众号菜单跳转的URL地址进行编码
	 * @param goToUrl 跳转连接
	 * @return 编码后的字段串
	 */
	private String encodeGoToURL(String goToUrl){
		if (StringUtil.isNotNull(goToUrl)) {
			try {
				goToUrl = URLEncoder.encode(goToUrl, "UTF-8");
			} catch (UnsupportedEncodingException e) {
				logger.error("微信公众号菜单跳转地址编码失败", e);
			}
			return goToUrl;
		}else{
			return null;
		}
	}
	
	/**
	 * 对微信公众号菜单跳转的URL地址进行解码
	 * @param goToUrl 跳转连接
	 * @return 编码后的字段串
	 */
	private String decodeGoToURL(String goToUrl){
		if (StringUtil.isNotNull(goToUrl)) {
			try {
				goToUrl = URLDecoder.decode(goToUrl, "UTF-8");
			} catch (UnsupportedEncodingException e) {
				logger.error("微信公众号菜单跳转地址解码失败", e);
			}
			return goToUrl;
		}else{
			return null;
		}
	}
	
	/**
	 * 绑定账号
	 * @param request
	 * @param mobile 手机号
	 * @param verificationCode 验证码
	 * @return
	 * @author: solin
	 * @date: 2017年11月16日 下午5:13:25
	 */
	@RequestMapping("/bindAccount")
	public String bindAccount(HttpServletRequest request, String mobile, String  receiveVerifyCode) {
		request.setAttribute("mobile", mobile);
		request.setAttribute("verificationCode", receiveVerifyCode);
		
		//redis中的验证码KEY
		String verifyCodeKey = MyConstants.MOBILE_VERIFY_CODE_KEY.concat(IPUtils.getIntenetIP(request));
		//redis中的验证码值
		String sendVerifyCode = redisService.get(verifyCodeKey);
		if (String.valueOf(receiveVerifyCode).equals(sendVerifyCode)) {
			//校验成功后将验证码缓存清空
			redisService.del(verifyCodeKey); 
			try {
				//通过手机号到数据库中查询用户信息
				Map<String, Object> param = new HashMap<String, Object>();
				param.put("mobile", mobile);
				List<UserEntity> userList = userService.getUserList(param);
				if (userList.size() > 0) { //如果用户存在
					//判断用户是否已经审核通过
					for (int i = 0; i < userList.size(); i++) { //如果正在审核中
						if (USER_APPROVE_STATUS.PENDING.getId().equals(userList.get(i).getStatus())) {
							request.setAttribute(PublicStatus.RESULT_MSG, "账号信息正在审核中！");
							return "wx/my/bindAccount";
						} else if (USER_APPROVE_STATUS.AGREE.getId().equals(userList.get(i).getStatus())) { //如果审核通过
							//更新客户表和用户表中openId
							Integer userTyoe = userList.get(i).getUserType(); //用户类型
							
							//判断openId是否已更新到数据库中
							if (StringUtil.isEmpty(userList.get(i).getOpenId())) {
								//从cookie中获取openId
								String openId = WechatUtil.getOpenIdFromCookie(request);
								if (USER_TYPE.CUSTOMER.getId().equals(userTyoe)) { //如果用户类型是客户
									//查询客户信息
									Map<String, Object> csutomerParamMap = new HashMap<String, Object>();
									csutomerParamMap.put("status", USER_APPROVE_STATUS.AGREE.getId());
									csutomerParamMap.put("loginCode", userList.get(i).getMobile());
									List<CustomerEntity> customerList = customerService.listCustomer(csutomerParamMap);
									if (customerList.size() == 1) {
										//更新客户表中openId
										CustomerEntity customerEntityParam = new CustomerEntity();
										customerEntityParam.setId(customerList.get(0).getId());
										customerEntityParam.setOpenId(openId);
										customerService.updateCustomer(customerEntityParam);
									}
								}
								//更新用户表中openId
								UserEntity userEntityParam = new UserEntity();
								userEntityParam.setId(userList.get(i).getId());
								userEntityParam.setOpenId(openId);
								userService.updateUser(userEntityParam);
								
							}
							//shiro登录
							Subject currentUser = SecurityUtils.getSubject();
							UsernamePasswordToken token = new UsernamePasswordToken();
							token.setUsername(userList.get(i).getUserCode());
							token.setPassword(userList.get(i).getPassword().toCharArray()); 
							token.setLoginTerminal(PublicStatus.LOGIN_TERMINAL_TYPE.WX.getCode());
							currentUser.login(token);
							//跳转到首页
							if (!USER_TYPE.CUSTOMER.getId().equals(userTyoe)) {
								return "redirect:/wx/bizman/index"; //商户首页
							}
							return "redirect:/wx/index";  //客户首页
						}
					}
					//如果是审核驳回
					request.setAttribute(PublicStatus.RESULT_MSG, "账号审核未通过，已被驳回！");
					return "wx/my/bindAccount";
				} else {
					request.setAttribute(PublicStatus.RESULT_MSG, "该手机号未注册，不能进行绑定！");
					return "wx/my/bindAccount";
				}
			} catch (Exception e) {
				logger.error("==>账号绑定失败:{}", e);
				request.setAttribute(PublicStatus.RESULT_MSG, "账号绑定失败！");
				return "wx/my/bindAccount";
			}
		} else {
			request.setAttribute(PublicStatus.RESULT_MSG, "验证码不正确！");
			return "wx/my/bindAccount";
		} 
	}
	
	/**
	 * 发送短信验证码
	 * 修改逻辑： 注册优化，未审核的用户也可以绑定微信openid
	 * @param request
	 * @param mobile
	 * @return
	 * @author: solin
	 * @date: 2017年12月25日 下午7:18:28
	 */
	@RequestMapping("/sendBindUserVerifyCode")
	@ResponseBody
	public Map<String, Object> sendVerifyCode(HttpServletRequest request, String mobile) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		//如果是绑定用户，则需要先判断用户存不存在
		//通过手机号到数据库中查询用户信息
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("mobile", mobile);
		List<UserEntity> userList = userService.getUserList(param);
		if (userList !=null && userList.size() > 0) {
			try {
				//发送短信
				sendShortMsg(request, mobile);
				resultMap.put(PublicStatus.RESULT_CODE, "1");
				resultMap.put(PublicStatus.RESULT_MSG, "短信验证码发送成功！");
			} catch (Exception e) {
				logger.error("短信验证码发送失败:{}", e);
				resultMap.put(PublicStatus.RESULT_CODE, "0");
				resultMap.put(PublicStatus.RESULT_MSG, "短信验证码发送失败,请稍候再试！");
			}
			return resultMap;
		} else {
			resultMap.put(PublicStatus.RESULT_CODE, "0");
			resultMap.put(PublicStatus.RESULT_MSG, "该手机号未注册,请先注册！");
			return resultMap;
		}
	}
	
	/**
	 * 发送短信验证码
	 * @param request
	 * @param mobile
	 * @return
	 * @author: solin
	 * @date: 2017年12月25日 下午7:11:03
	 */
	private boolean sendShortMsg(HttpServletRequest request, String mobile) {
		boolean sendStatus = false;
		// redis中的验证码KEY
		String verifyCodeKey = MyConstants.MOBILE_VERIFY_CODE_KEY.concat(IPUtils.getIntenetIP(request));
		// 发送短信
//		String templateId = "SMS_126866486";
		String verifyCode = RandomUtils.getRandNum(6);
		// 保存到redis
		redisService.save(verifyCodeKey, verifyCode, (30 * 60));
		System.out.println("============>>>短信验证码:" + verifyCode);
		String params = "{\"code\":\"" + verifyCode + "\"}";
		sendStatus = AliyunSmsUtils.sendSms(SmsTemplateType.SMS_VALID.getTemplateId(), mobile, params);
		return sendStatus;
	}
}
